<template>
  <div>
    <drop-down-tree
      :tree-data="sortTreeData"
      id-name="id"
      children-name="children"
      :expand-map="expandMap"
      :className="className"
    >
      <template
        slot="title"
        slot-scope="{ id, data, parentId, index, parentIds, isExpand, hasContent }"
      >
        <div
          class="expand-title"
          @dragstart.stop="ondragstart($event, id, parentId, index)"
          @dragover.stop="ondragover($event, parentId, index, parentIds)"
          @dragend="ondragend()"
        >
          <span v-if="hasContent" class="expand-botton">
            <span v-if="isExpand" class="fa fa-minus" @click="setExpandMap(id, false)"></span>
            <span v-else class="fa fa-plus" @click="setExpandMap(id, true)"></span>
          </span>
          <span
            class="expand-content"
            @dragover.stop="ondragover($event, id, 0, [...parentIds, id])"
          >
            {{ data.name }}
            <i v-if="id" class="fa fa-arrows" draggable></i>
          </span>
        </div>
      </template>
    </drop-down-tree>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";

import DropDownTree from "@/components/drop-down-tree/index.vue";

import { treeSwap } from "@/utils/treeUtis";

@Component({
	name: 'TreeTestView',
	components: {
		DropDownTree,
	},
})
export default class TreeTestView extends Vue {

  public treeData = {
		id: null,
		name: '测试树列表',
		_is_open: true,
		children: [
			{ id: 12, name: 'j' },
			{
				id: 1,
				name: 'a',
				children: [
					{ id: 2, name: 'a-1' },
					{ id: 3, name: 'a-2' },
				],
			},
			{ id: 4, name: 'b' },
			{ id: 5, name: 'c' },
			{ id: 6, name: 'd' },
			{ id: 7, name: 'e' },
			{ id: 8, name: 'f' },
			{ id: 9, name: 'g' },
			{ id: 10, name: 'h' },
			{ id: 11, name: 'i' },
		],
	};

  public expandMap: { [key in string]: boolean } = {};

  setExpandMap(key: string, value: boolean) {
    this.expandMap[key] = value;
    this.expandMap = { ...this.expandMap };
  }

  private dragInfo = {
    draging: false,
    overTiemoutId: 0,
    from: { id: -1, parentId: null, index: null },
    temp: { parentId: null, index: null },
    to: { parentId: null, index: null },
  };

  public className({ id }) {
    if (this.dragInfo.draging && this.dragInfo.from.id === id) {
      return "drop-down-tree-draging";
    } else {
      return "";
    }
  }

  public get sortTreeData() {
    const data = JSON.parse(JSON.stringify(this.treeData));
    if (this.dragInfo.draging && typeof this.dragInfo.from.index === "number" && typeof this.dragInfo.to.index === "number") {
      treeSwap(
        data,
        (info) => info.id,
        (info) => info.children = (info.children || []),
        this.dragInfo.from.parentId,
        this.dragInfo.from.index,
        this.dragInfo.to.parentId,
        this.dragInfo.to.index,
      );
      return data;
    }
    return data;
  }

  public ondragstart(event: DragEvent, id: any, parentId: any, index: any) {
    if (parentId === -1) {
      event.preventDefault();
      return;
    }
    if (this.dragInfo.draging) {
      this.ondragend();
    }
    this.dragInfo.draging = true;
    this.dragInfo.from.id = id;
    this.dragInfo.from.parentId = parentId;
    this.dragInfo.from.index = index;
  }

  public ondragover(event: DragEvent, parentId: any, index: any, parentIds: any[]) {
    if (!this.dragInfo.draging) {
      return;
    }
    if (parentId === -1) {
      return;
    }
    if (parentIds.includes(this.dragInfo.from.id)) {
      return;
    }
    if (this.dragInfo.temp.parentId !== parentId || this.dragInfo.temp.index !== index) {
      if (this.dragInfo.overTiemoutId) {
        clearTimeout(this.dragInfo.overTiemoutId);
        this.dragInfo.overTiemoutId = 0;
      }
      this.dragInfo.temp.parentId = parentId;
      this.dragInfo.temp.index = index;
      this.dragInfo.overTiemoutId = setTimeout(() => {
        this.dragInfo.to.parentId = this.dragInfo.temp.parentId;
        this.dragInfo.to.index = this.dragInfo.temp.index;
        // if (this.expandMap[this.dragInfo.temp.parentId] !== true) {
        //   this.expandMap[this.dragInfo.temp.parentId] = true;
        // }
      }, 100);
    }
  }

  public ondragend() {
    if (!this.dragInfo.draging) {
      return;
    }
    this.treeData = this.sortTreeData;
    this.dragInfo.draging = false;
    if (this.dragInfo.overTiemoutId) {
      clearTimeout(this.dragInfo.overTiemoutId);
      this.dragInfo.overTiemoutId = 0;
    }
    this.dragInfo.from.id = -1;
    this.dragInfo.from.parentId = null;
    this.dragInfo.from.index = null;
    this.dragInfo.temp.parentId = null;
    this.dragInfo.temp.index = null;
    this.dragInfo.to.parentId = null;
    this.dragInfo.to.index = null;
    this.dragInfo = { ...this.dragInfo };
  }

}
</script>

<style lang="scss" scoped>
.fa {
  margin: 2px 5px;
  cursor: pointer;
  color: #cb2431;
}

.expand-title {
  min-height: 20px;

  &:hover {
		background-color: #bababa;
		transition: background-color 0.2s;
  }
}

.expand-content {
  margin: 2px 5px;
  display: inline-block;
  min-width: 100px;
}
</style>

<style lang="scss" scoped>
::v-deep .drop-down {

	.drop-down-body {
		transition-duration: .2s;
	}

	.drop-down-content {
		position: relative;
		margin-left: 30px;
		padding-left: 10px;

		& > * {
			position: relative;

			&:before {
				position: absolute;
				display: inline-block;
				content: '';
				top: -5px;
				bottom: 0;
				left: -28px;
				width: 28px;
				height: 15px;
				border-bottom: 1px solid;
				border-left: 1px solid;
			}

			&:after {
				position: absolute;
				display: inline-block;
				content: '';
				top: 10px;
				bottom: 5px;
				left: -28px;
				width: 26px;
				border-left: 1px solid;
			}

			&:last-child:after {
				display: none;
			}
		}
	}
}

::v-deep .drop-down-tree-draging {
  .drop-down-title {
    background-color: greenyellow;

    &:hover {
      background-color: greenyellow;
    }
  }

  .expand-title {
    &:hover {
      background-color: greenyellow;
    }
  }
}
</style>
